package tmt.usercenter.web.service;

import com.tmt.annotation.ReflectInvoked;
import com.tmt.datatable.ext.controller.SelectOptions;
import com.tmt.helper.ReflectHelper;
import com.tmt.helper.StringHelper;
import com.tmt.spring.validation.RequiredField;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tmt.usercenter.web.domain.ClientSystem;
import tmt.usercenter.web.domain.TmtUser;
import tmt.usercenter.web.domain.UserInfoConfig;
import tmt.usercenter.web.repository.IUserRegisterConfigRepo;
import tmt.usercenter.web.vo.user.RegisterVo;

import java.lang.reflect.Field;
import java.util.*;

@Service
@Transactional(rollbackFor = Exception.class)
public class UserInfoConfigService extends TmtBaseService<UserInfoConfig, Long> {

    @Getter

    private IUserRegisterConfigRepo iUserRegisterConfigRepo;
    private ClientSystemService clientSystemService;
    private TmtUserService userService;

    @Autowired
    public UserInfoConfigService(IUserRegisterConfigRepo iUserRegisterConfigRepo,
                                 ClientSystemService clientSystemService,
                                 TmtUserService userService) {
        super(iUserRegisterConfigRepo, Arrays.asList(clientSystemService));
        this.iUserRegisterConfigRepo = iUserRegisterConfigRepo;
        this.clientSystemService = clientSystemService;
        this.userService = userService;
    }

    @ReflectInvoked("本方法被反射调用了")
    public UserInfoConfig findByOriginSystemClientId(String clientId, boolean createIfNotExist) {
        UserInfoConfig config = iUserRegisterConfigRepo.findByOriginSystem_ClientId(clientId);
        try {
            if (config == null && createIfNotExist) {
                ClientSystem clientSystem = clientSystemService.findByClientId(clientId);
                config = createDefaultUserRegisterConfig(clientSystem.getCreator(), clientSystem);
                config = create(config);
            }
        } catch (Exception ex) {
        }
        return config;
    }

    private UserInfoConfig createDefaultUserRegisterConfig(TmtUser creator, ClientSystem clientSystem) {
        UserInfoConfig userRegisterConfig = new UserInfoConfig();
        userRegisterConfig.setRequiredInfo(new ArrayList<>(getUserRegisterFields().keySet()));
        userRegisterConfig.setCreator(creator);
        userRegisterConfig.setOriginSystem(clientSystem);
        try {
            userRegisterConfig = create(userRegisterConfig);
            if (userRegisterConfig.getCreator() != creator) {
                userRegisterConfig.setCreator(creator);
                userRegisterConfig = update(userRegisterConfig);
            }
        } catch (Exception ex) {
        }
        return userRegisterConfig;
    }

    @Transactional(readOnly = true)
    public SelectOptions getUserRegisterFieldsForSelect2() {
        SelectOptions selectOptions = new SelectOptions();
        try {
            List<Field> fieldList = ReflectHelper.findAllFieldByAnnotation(RegisterVo.class, RequiredField.class, -1);
            fieldList.stream().sorted((x, y) -> {
                int xOrder = x.getAnnotation(RequiredField.class).order();
                int yOrder = y.getAnnotation(RequiredField.class).order();
                return Integer.compare(xOrder, yOrder);
            }).forEach(x -> {
                RequiredField annotation = x.getAnnotation(RequiredField.class);
                Map<String, Object> map = new HashMap<>();
                map.put("id", x.getName());
                map.put("text", annotation.label());
                selectOptions.addItem(map);
            });
        } catch (Exception ex) {
        }

        return selectOptions;
    }

    @Transactional(readOnly = true)
    public Map<String, String> getUserRegisterFields() {
        Map<String, String> map = new LinkedHashMap<>();
        List<Field> fieldList = ReflectHelper.findAllFieldByAnnotation(RegisterVo.class, RequiredField.class, -1);
        fieldList.stream().sorted((x, y) -> {
            int xOrder = x.getAnnotation(RequiredField.class).order();
            int yOrder = y.getAnnotation(RequiredField.class).order();
            return Integer.compare(xOrder, yOrder);
        }).forEachOrdered(x -> {
            map.put(x.getName(), x.getAnnotation(RequiredField.class).label());
        });
        return map;
    }

    /**
     * 在指定的客户端系统内字段是否配置了唯一要求
     *
     * @param clientId  客户端编号
     * @param fieldName 需要唯一的字段
     * @return 字段是否配置唯一性
     */
    public boolean uniqueField(String clientId, String fieldName) {
        UserInfoConfig config = findByOriginSystemClientId(clientId, false);
        return config != null && config.getUniqueFields() != null && config.getUniqueFields().contains(fieldName);

    }

    public void validateMobileRule(String mobile, Long notUserId, String clientId) throws Exception {
        //手机号码唯一性判决
        UserInfoConfig config = findByOriginSystemClientId(clientId, false);
        if (config == null)
            return;

        if (config.getUniqueFields().contains("mobile")) {
            boolean exists = userService.existsInClientSystemBy(clientId, "mobile", mobile, notUserId);
            if (exists) {
                throw new Exception("手机号码重复");
            }
        } else if (config.getMaxSameMobile() > 0) {
            //如果手机号码不为空，则判断当前客户系统允许相同手机号码注册的最大用户数量参数，并进行判断。
            List<Long> systemIds = Collections.singletonList(config.getOriginSystem().getId());
            if (!StringHelper.isEmpty(config.getClientGroupId())) {
                systemIds = getIUserRegisterConfigRepo().getOriginSystemIdsByClientGroupId(config.getClientGroupId());
            }
            long count = userService.getITmtUserRepo().countByMobileAndOriginSystemIdIn(mobile, systemIds);
            if (count > config.getMaxSameMobile()) {
                throw new Exception(String.format("手机号码 %s 已达到最大用户注册数：%s", mobile, config.getMaxSameMobile()));
            }
        }
    }
}
